package com.starlight.flower_server.controller.interceptor;

import com.starlight.flower_server.controller.authentication.AuthenticationCheck;
import com.starlight.flower_server.controller.exception.ForbiddenException;
import com.starlight.flower_server.infrastructure.RoleType;
import com.starlight.flower_server.infrastructure.Status;
import com.starlight.flower_server.infrastructure.util.CurrentUserInfoUtils;
import com.starlight.flower_server.infrastructure.util.JwtUtils;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

/**
 * @Author yfy2001
 * @date 2023/4/10 8:49
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Resource
    JwtUtils jwtUtils;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 请求处理前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler)            throws Exception {
        /**
         * 识别注解进行登录拦截和权限拦截
         * 无注解直接跳过认证
         * 有注解则需要用户登录
         */
        if (handler instanceof  HandlerMethod){
            //获取请求基本信息
            //        //获取header所有内容
//        Enumeration<String> headerNames = request.getHeaderNames();
//        while(headerNames.hasMoreElements()) {//判断是否还有下一个元素
//            String nextElement = headerNames.nextElement();//获取headerNames集合中的请求头
//            String header2 = request.getHeader(nextElement);//通过请求头得到请求内容
//            System.out.println(nextElement+":"+header2);
//        }
            //获取ip和归属地信息
            String ip=request.getHeader("ip");
            String addressCode=request.getHeader("address");
            String address="";
            if (addressCode!=null){
                address= URLDecoder.decode(addressCode, StandardCharsets.UTF_8);
            }
//            System.out.println("\n\nip:"+ip);
//            System.out.println("address:"+address);
            //获取请求头的ua标识,解析agent字符串
            UserAgent userAgent=UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
            //获取浏览器对象
            Browser browser = userAgent.getBrowser();
            //获取操作系统对象
            OperatingSystem operatingSystem = userAgent.getOperatingSystem();
//        System.out.println("浏览器名:"+browser.getName());
//        System.out.println("浏览器类型:"+browser.getBrowserType());
//        System.out.println("浏览器家族:"+browser.getGroup());
//        System.out.println("浏览器生产厂商:"+browser.getManufacturer());
//        System.out.println("浏览器使用的渲染引擎:"+browser.getRenderingEngine());
//        System.out.println("浏览器版本:"+userAgent.getBrowserVersion());
//
//        System.out.println("操作系统名:"+operatingSystem.getName());
//        System.out.println("访问设备类型:"+operatingSystem.getDeviceType());
//        System.out.println("操作系统家族:"+operatingSystem.getGroup());
//        System.out.println("操作系统生产厂商:"+operatingSystem.getManufacturer());

            String device=operatingSystem.getName()+" "+browser.getName();
            CurrentUserInfoUtils.set("ip",ip);
            CurrentUserInfoUtils.set("address",address);
            CurrentUserInfoUtils.set("device",device);
            //跳过权限验证
//            if (true){
//                return true;
//            }
            //判断是否需要登录
            AuthenticationCheck authenticationCheck
                    =((HandlerMethod)handler).getMethodAnnotation(AuthenticationCheck.class);
            if (authenticationCheck==null){
                return true;
            }
            //从请求中获取token
            String token=request.getHeader("token");
            String username;
            String userRole;
            String userId;
            if (Boolean.TRUE.equals(redisTemplate.hasKey(token))){
                userId= String.valueOf(jwtUtils.getUserId(token));
                username= jwtUtils.getUsername(token);
                userRole = redisTemplate.opsForValue().get(token);
                CurrentUserInfoUtils.set("token",token);
                CurrentUserInfoUtils.set("userId",userId);
                CurrentUserInfoUtils.set("username",username);
                CurrentUserInfoUtils.set("userRole",userRole);
                System.out.println("携带的token:"+token);
                System.out.println("用户id:"+userId);
                System.out.println("用户名:"+username);
                System.out.println("权限:"+userRole);
            }else {
                throw new ForbiddenException(Status.LOGIN_REQUIRED.getMessage(), Status.LOGIN_REQUIRED);
            }
            for (RoleType roles: authenticationCheck.roleType()) {
                if (roles.toString().equals(userRole)){
                    return true;
                }
            }
        }else if(handler instanceof ResourceHttpRequestHandler) {
            return true;
        }
        throw new ForbiddenException(Status.PERMISSION_DENIED.getMessage(), Status.PERMISSION_DENIED);
    }

    /**
     * 请求完成后执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           @Nullable ModelAndView modelAndView)
            throws Exception {

    }

    /**
     * 请求结束后执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                @Nullable Exception ex) throws Exception {

    }
}
